package com.wanghua.spring.test.json;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import org.junit.Assert;
import org.junit.Test;

import java.lang.reflect.Modifier;

public class GsonDemo {
    class MyObj {
        @Expose
        public transient int x;
        @Expose
        public int y;
        @Expose
        protected int z;
        public int _a;

        public MyObj(int x, int y, int z, int _a) {
            this.x = x;
            this.y = y;
            this.z = z;
            this._a = _a;
        }
    }

    @Test
    public void gson() {
        MyObj obj = new MyObj(1, 2, 3, 6);

        //1.带 transient 的不会被序列化（此方式对“protected、注解”透明）
        //注：如果使用 transient，hibernate获取数据时，这个字段值会为null，即使用了饥渴加载。
        Gson gson = new Gson();
        String str = gson.toJson(obj);

        //2.排除 protected 的字段（此方式对“transient”透明，即不设置 protected，带 transient 的也会被序列化）
        gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PROTECTED).create();
        str = gson.toJson(obj);

        //3.没有被 @Expose 标注的字段会被排除（使用此方式，即使注解了，但如果设置 transient 也不能序列化出来。但与 “protected”无关）
        gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        str = gson.toJson(obj);

        //4.使用ExclusionStrategy定制字段排除策略（这种方式最灵活，下面的例子把所有以下划线开头的字段全部都排除掉）
        //注：带 transient 的会自动被排除的，不需要下面设置的。
        ExclusionStrategy myExclusionStrategy = new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fa) {
                return fa.getName().startsWith("_");
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return false;
            }
        };
        gson = new GsonBuilder().setExclusionStrategies(myExclusionStrategy).create();
        str = gson.toJson(obj);

        Assert.assertEquals("{\"x\":1,\"y\":2}", str);
    }
}
